﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Qu.ComputingContest.Model;
using System.Text;
using System.Runtime.Caching;
using Qu.SeniorProject.WebUI.Utils;

namespace Qu.ComputingContest.WebUI.Controllers
{ 
    public class ScoreController : Controller
    {
        private ComputingContestDB db = new ComputingContestDB();
        public ICacheProvider Cache = new DefaultCacheProvider();
        
        private void PopulateDropDowns(int registrationId, string formTitle)
        {
            ViewBag.RegistrationID = new SelectList(GetTeams(), "RegistrationID", "TeamNo", registrationId);

            ViewBag.FormTitle = formTitle;
        }


        private IEnumerable<Registration> GetTeams()
        {
            // First, check the cache
            IEnumerable<Registration> teams = Cache.Get("teams") as IEnumerable<Registration>;

            // If it's not in the cache, we need to read it from the repository
            if (teams == null)
            {
                int currentYear = DateTime.Now.Year;
                // Get the repository data
                teams = db.Registrations.Where(r => r.IsActive && r.Year == currentYear).ToList();

                if (teams.Any())
                {
                    foreach (var team in teams)
                    {
                        team.Team = db.Database.SqlQuery<string>(string.Format("Select dbo.GetSchoolName({0})", team.RegistrationID)).SingleOrDefault();
                        //team.Team = string.Format("{0} - {1}", team.RegistrationID, team.Team);
                    }
                    // Put this data into the cache for 30 minutes
                    Cache.Set("teams", teams, 60);
                }
            }
            return teams.OrderBy(t => t.TeamNo);
        }

        //
        // GET: /Score/

        public string GetSchoolName(int registrationID)
        {
            IEnumerable<Registration> teams = GetTeams();
            var team = teams.Where(t => t.RegistrationID == registrationID).SingleOrDefault();
            if (team != null)
                return team.Team;
            else
                return "Team not found";
        }

        public ViewResult Schedule(string time)
        {
            TimeSpan timeParam = new TimeSpan(DateTime.Now.Hour, DateTime.Now.Minute, 0);
            if (!string.IsNullOrEmpty(time))
                timeParam = new TimeSpan(int.Parse(time.Split(':')[0]), int.Parse(time.Split(':')[1]), 0);

            //var trackTeams = db.GetSchedule(timeParam).ToList();
            var trackTeams = db.Database.SqlQuery<ScheduleItem>(string.Format("exec GetSchedule '{0}'", timeParam.ToString())).ToList();

            ViewBag.IsScoreBoard = true;

            return View(trackTeams);
        }

        public ViewResult ScoreBoard()
        {
            //Auto-Refresh every 60 seconds
            //int numWinners = 6;
            int numWinners = ScoreRepository.NumWinnersOnScoreboard();
            //Response.AddHeader("Refresh", "180");
            string scoreboardRefreshTimeSpan = ScoreRepository.ScoreboardRefreshTimeSpan().ToString();
            ViewBag.ScoreboardRefreshTimeSpan = scoreboardRefreshTimeSpan;
            Response.AddHeader("Refresh", scoreboardRefreshTimeSpan);

            int currentContestYear = DateTime.Now.Year; //Qu.ComputingContest.Model.RegistrationRepository.GetCurrentContestYear();

            ViewBag.IsScoreBoard = true;
            var scores = db.Database.SqlQuery<ScoreSummary>(string.Format("exec GetScoresSummary {0}, {1}", currentContestYear, 1)).ToList();

            var finalScores = db.Database.SqlQuery<ScoreSummary>(string.Format("exec GetScoresSummary {0}, {1}, {2}, {3}", currentContestYear, 1, 0, 1)).ToList();
            
            List<ScoreSummary> top5Scores = null;
            List<ScoreSummary> otherScores = null;
            if (finalScores != null && finalScores.Count > 0)
            {
                ViewBag.FinalScores = finalScores.ToList().Take(numWinners); 
                otherScores = scores;
            }
            else
            {
                top5Scores = scores.Take(numWinners).ToList(); //Where(s => s.Rank <= numWinners).
                otherScores = scores.Where(s => !top5Scores.Contains(s)).ToList();
            }

            if (top5Scores != null && top5Scores.Count > 0)
                ViewBag.Top5Scores = top5Scores;

            if (otherScores != null && otherScores.Count > 0)
                ViewBag.OtherScores = otherScores;

            if (Request.IsAjaxRequest())
                return View(scores);
            else
                return View(scores);
        }

        [Authorize]
        public ViewResult Index()
        {
            ViewBag.IsScoreBoard = false;
            //var scores = db.Database.SqlQuery<ScoreSummary>(string.Format("exec GetScoresSummary {0}, {1}", DateTime.Now.Year, 0)).OrderByDescending(s => s.DateAt).ToList();
            int currentContestYear = DateTime.Now.Year;
            var scores = db.Database.SqlQuery<ScoreSummary>(string.Format("exec GetScoresSummary {0}, {1}", currentContestYear, 0)).ToList();
            return View(scores.ToList());
        }

        //
        // GET: /Score/Details/5
        public ViewResult Details(int id)
        {
            Score score = db.Scores.Find(id);
            return View(score);
        }

        //
        // GET: /Score/Create
        [Authorize]
        public ActionResult Add()
        {
            ViewBag.IsFinalRound = ScoreRepository.IsFinalRound();
            Score score = new Score();
            score.UpdatedBy = User.Identity.Name;
            if (string.IsNullOrEmpty(score.UpdatedBy))
                score.UpdatedBy = "sa";
            score.UpdatedDate = DateTime.Now;
            PopulateDropDowns(0, "Add Score");
            return View(score);
        }

        [Authorize]
        public ActionResult StartFinalRound()
        {
            string finalRoundDateTime = DateTime.Now.ToString();
            ScoreRepository.SetStartFinalRound(finalRoundDateTime);
            TempData["Message"] = "Start Final Round flag was sucessfully set";
            return RedirectToAction("Index");
        }

        [Authorize]
        public ActionResult UndoStartFinalround()
        {
            string finalRoundDateTime = null;
            ScoreRepository.SetStartFinalRound(finalRoundDateTime);
            TempData["Message"] = "Start Final Round flag was sucessfully undone";
            return RedirectToAction("Index");
        } 

        //
        // POST: /Score/Create

        [Authorize]
        [HttpPost]
        public ActionResult Add(Score score, string minutes, string seconds, string miliSeconds)
        {
            ViewBag.IsFinalRound = ScoreRepository.IsFinalRound();

            int num;
            if ((!string.IsNullOrEmpty(minutes) && !int.TryParse(minutes, out num)) 
                    || (!string.IsNullOrEmpty(seconds) && !int.TryParse(seconds, out num))
                    || (!string.IsNullOrEmpty(miliSeconds) &&  !int.TryParse(miliSeconds, out num)))
            {
                ModelState.AddModelError("RegistrationID", "Runtime values must be digits");
            }

            if (ModelState.IsValid)
            {
                if (!string.IsNullOrEmpty(minutes))
                    score.RunTime += int.Parse(minutes) * 60;

                if (!string.IsNullOrEmpty(seconds))
                    score.RunTime += int.Parse(seconds);

                if (!string.IsNullOrEmpty(miliSeconds))
                    score.RunTime += (decimal.Parse(miliSeconds) / 100);

                var sb = new StringBuilder();
                score.UpdatedBy = User.Identity.Name;
                if (string.IsNullOrEmpty(score.UpdatedBy))
                    score.UpdatedBy = "sa";

                sb.Append("exec InsertScore ");
                sb.AppendFormat("@RegistrationID = {0}, ", score.RegistrationID);
                sb.AppendFormat("@RunTime = {0}, ", score.RunTime);
                sb.AppendFormat("@DispalyCorrectColor = {0}, ", score.DispalyCorrectColor);
                sb.AppendFormat("@StopAtCorrectFinishBox = {0}, ", score.StopAtCorrectFinishBox);
                sb.AppendFormat("@StoppedInFirstHalf = {0}, ", score.StoppedInFirstHalf);
                sb.AppendFormat("@StoppedInSecondHalf = {0}, ", score.StoppedInSecondHalf);
                sb.AppendFormat("@FellOffBridgeWithinTrack = {0}, ", score.FellOffBridgeWithinTrack);
                sb.AppendFormat("@FailedToDragBlock = {0}, ", score.FailedToDragBlock);
                sb.AppendFormat("@UpdatedBy = {0}", score.UpdatedBy);

                db.Database.ExecuteSqlCommand(sb.ToString());
                //db.Scores.Add(score);
                //db.SaveChanges();

                int? teamNo = ScoreRepository.GetTeamNo(score.RegistrationID);
                if (teamNo != null)
                    TempData["Message"] = string.Format("Score for Team {0} added sucessfully", teamNo);
                else
                    TempData["Message"] = string.Format("Saving the score failed");
                //var newScore = new Score();
                //newScore.UpdatedBy = User.Identity.Name; 
                //ViewBag.RegistrationID = new SelectList(GetTeams(), "RegistrationID", "RegistrationID");

                //newScore.UpdatedDate = DateTime.Now;

                //return View(newScore);

                return RedirectToAction("Add");  
            }

            PopulateDropDowns(score.RegistrationID, "Add Score");
            return View(score);
        }
        
        //
        // GET: /Score/Edit/5
        [Authorize]
        public ActionResult Edit(int id)
        {
            ViewBag.IsFinalRound = ScoreRepository.IsFinalRound();
            Score score = db.Scores.Find(id);
            PopulateDropDowns(score.RegistrationID, "Edit Score");
            return View("Add", score);
        }

        //
        // POST: /Score/Edit/5
        [Authorize]
        [HttpPost]
        public ActionResult Edit(Score score)
        {
            if (ModelState.IsValid)
            {
                db.Entry(score).State = EntityState.Modified;
                score.UpdatedBy = User.Identity.Name;
                if (string.IsNullOrEmpty(score.UpdatedBy))
                    score.UpdatedBy = "sa";
                score.UpdatedDate = DateTime.Now;
                db.SaveChanges();
                return RedirectToAction("Index");
            }
            ViewBag.IsFinalRound = ScoreRepository.IsFinalRound();
            PopulateDropDowns(score.RegistrationID, "Edit Score");
            return View("Add", score);
        }

        //
        // GET: /Score/Delete/5
        [Authorize]
        public ActionResult Delete(int id)
        {
            Score score = db.Scores.Find(id);
            return View(score);
        }

        //
        // POST: /Score/Delete/5
        [Authorize]
        [HttpPost, ActionName("Delete")]
        public ActionResult DeleteConfirmed(int id)
        {            
            Score score = db.Scores.Find(id);
            db.Scores.Remove(score);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        protected override void Dispose(bool disposing)
        {
            db.Dispose();
            base.Dispose(disposing);
        }

        public ActionResult Ping()
        {
            return Content(".");
        }
    }
}